The use of object-oriented programming techniques can facilitate the development of complex computer programs. Programming languages that support object-oriented techniques have been developed. One such programming language is C++.
Two common characteristics of object-oriented programming languages are support for data encapsulation and data type inheritance. Data encapsulation refers to the binding of functions and data. Inheritance refers to the ability to declare a data type in terms of other data types.
In the C++ language, object-oriented techniques are supported through the use of classes. A class is a user-defined type. A class declaration describes the data members and function members of the class. For example, the following declaration defines data members and a function member of a class named CIRCLE.
______________________________________ class CIRCLE { int x, y; int radius; void draw( ); }; ______________________________________
Variables x and y specify the center location of a circle and variable radius specifies the radius of the circle. These variables are referred to as data members of the class CIRCLE. The function draw is a user-defined function that draws the circle of the specified radius at the specified location. The function draw is referred to as a function member of class CIRCLE. The data members and function members of a class are bound together in that the function operates on an instance of the class. An instance of a class is also called an object of the class.
In the syntax of C++, the following statement declares the objects a and b to be of type class CIRCLE. EQU CIRCLE a, b;
This declaration causes the allocation of memory for the objects a and b, such an allocation is called an instance of the class. The following statements assign data to the data members of objects a and b. EQU a.x=2; EQU a.y=2; EQU a.radius=1; EQU b.x=4; EQU b.y=5; EQU b.radius=2;
The following statements are used to draw the circles defined by objects a and b. EQU a.draw( ); EQU b.draw( );
A derived class is a class that inherits the characteristics--data members and function members--of its base classes. For example, the following derived class CIRCLE.sub.-- FILL inherits the characteristics of the base class CIRCLE.
______________________________________ class CIRCLE.sub.-- FILL : CIRCLE { int pattern; void fill( ); }; ______________________________________
This declaration specifies that class CIRCLE.sub.-- FILL includes all the data and function members that are in class CIRCLE in addition to the those data and function members introduced in the declaration of class CIRCLE.sub.-- FILL, that is, data member pattern and function member fill. In this example, class CIRCLE.sub.-- FILL would have data members x, y, radius, and pattern and function members draw and fill. Class CIRCLE.sub.-- FILL is said to "inherit" the characteristics of class CIRCLE. A class that inherits the characteristics of another class is a derived class (e.g., CIRCLE.sub.-- FILL). A class that does not inherit the characteristics of another class is a primary class (e.g., CIRCLE). A class whose characteristics are inherited by another class is a base class (e.g., CIRCLE is a base class of CIRCLE.sub.-- FILL). A derived class may inherit the characteristics of several classes, that is, a derived class may have several base classes. This is referred to as multiple inheritance.
A derived class may specify that a base class is to be inherited virtually. Virtual inheritance of a base class means that only one instance of the virtual base class exists in the derived class. For example, the following is an example of a derived class with two non-virtual base classes. EQU class CIRCLE.sub.-- 1 : CIRCLE {. . . }; EQU class CIRCLE.sub.-- 2 : CIRCLE {. . . }; EQU class PATTERN : CIRCLE.sub.-- 1, CIRCLE.sub.-- 2{. . . };
In this declaration class PATTERN inherits class CIRCLE twice non-virtually through classes CIRCLE.sub.-- 1 and CIRCLE.sub.-- 2. There are two instances of class CIRCLE in class PATTERN.
The following is an example of a derived class with two virtual base classes. EQU class CIRCLE.sub.-- 1 : virtual CIRCLE {. . . }; EQU class CIRCLE.sub.-- 2 : virtual CIRCLE {. . . }; EQU class PATTERN: CIRCLE.sub.-- 1, CIRCLE.sub.-- 2{. . . };
The derived class PATTERN inherits class CIRCLE twice virtually through classes CIRCLE.sub.-- 1 and CIRCLE.sub.-- 2. Since the class CIRCLE is virtually inherited twice, there is only one object of class CIRCLE in the derived class PATTERN. One skilled in the art would appreciate that virtual inheritance can be very useful when the class derivation is more complex.
A class may also specify whether its function members are virtual. Declaring that a function member is virtual means that the function can be overridden by a function of the same name and type in a derived class. In the following example, the function draw is declared to be virtual in classes CIRCLE and CIRCLE.sub.-- FILL.
______________________________________ class CIRCLE { int x, y; int radius; virtual void draw( ); }; class CIRCLE.sub.-- FILL : CIRCLE { int pattern; virtual void draw( ); }; ______________________________________
The C++ language provides a pointer data type. A pointer holds values that are addresses of objects in memory. Through a pointer, an object can be referenced. The following statement declares variable c.sub.-- ptr to be a pointer on an object of type class CIRCLE and sets variable c.sub.-- ptr to hold the address of object c. EQU CIRCLE *c.sub.-- ptr; EQU cptr=&c
Continuing with the example, the following statement declares object a to be of type class CIRCLE and object b to be of type class CIRCLE.sub.-- FILL. EQU CIRCLE a; EQU CIRCLE.sub.-- FILL b;
The following statement refers to the function draw as defined in class CIRCLE. EQU a.draw( );
Whereas, the following statement refers to the function draw defined in class CIRCLE.sub.-- FILL. EQU b.draw( );
Moreover, the following statements type cast object b to an object of type class CIRCLE and invoke the function draw that is defined in class CIRCLE.sub.-- FILL.
______________________________________ CIRCLE c; CIRCLE *c.sub.-- ptr; c.sub.-- ptr = &b; c.sub.-- ptr.fwdarw.draw( ); // CIRCLE.sub.-- FILL::draw( ) ______________________________________
Thus, the virtual function that is called is function CIRCLE.sub.-- FILL::draw.
In addition to allowing pointers to objects of a class, the C++ language provides for pointers to function members or data members of a class. The following statement declares variable int.sub.-- ptr to be a pointer to an integer data member of class CIRCLE. EQU int CIRCLE::*int.sub.-- ptr;
The following statement sets pointer int.sub.-- ptr to point to the integer data member y of class CIRCLE. EQU int.sub.-- ptr=&CIRCLE::y;
In C++, a pointer to a member is bound to an object using the operator".*" and to a pointer to an object using the operator ".fwdarw.*". The following statements declare objects c and d to be of type class CIRCLE and use pointers to data members to set the values of data members x and y. EQU CIRCLE c, d; EQU int.sub.-- ptr=&CIRCLE::x; EQU c.*int.sub.-- ptr=4; EQU d.*int.sub.-- ptr=3; EQU int.sub.-- ptr=&CIRCLE::y; EQU c.*int.sub.-- ptr=5; EQU d.*int.sub.-- ptr=2;
The above statements are logically equivalent to the following statements, which use a more direct approach to setting the values. EQU CIRCLE C, d; EQU c.x=4; EQU d.x=3; EQU c.y=5; EQU d.y=2;
The following statement defines variable f.sub.-- ptr to be a pointer to a function member of class C with a return data type of void and no formal arguments. EQU void (CIRCLE::*f.sub.-- ptr) ( );
The following statement sets pointer f.sub.-- ptr to point to function draw of class CIRCLE. EQU f.sub.-- ptr=&CIRCLE::draw;
The following statements invoke function draw for an instance of a class CIRCLE. EQU CIRCLE c; EQU (c.*f.sub.-- ptr) ( );
The above statements are equivalent to the following statements. EQU CIRCLE c; EQU c.draw( );